package com.fanshuai.soring.boot.controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;

import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;

@RestController
@Slf4j
public class HelloController {
    @GetMapping("/hello")
    public String helloWorld() {
        return "hello world controller";
    }

    @GetMapping("/hello2")
    public String helloWorld2() {
        return "hello world servlet";
    }

    /**
     * 浏览器端如果需要滚动返回效果，需要添加header: accept-encoding: gzip, deflate, br
     * 否则在StreamingResponseBody输出完成之前，浏览器端http请求一直处于pending状态
     *
     * http1.1 默认开启keep-alive，因此无法以tcp连接关闭来判断http响应已完成。那么如何判断呢？
     *
     * 1 设置content-length。浏览器接收到content-length的数据时，默认已完成。如果content-length设置小于实际数据大小，则截断部分数据；
     * 如果如果content-length设置大于实际数据大小，则http请求一直处于pending状态
     * 2 设置Transfer-Encoding: trunked 此时http响应body分段传输。最后一段长度等于0时，响应结束
     * 3 设置Content-encoding: br    服务端返回以br分割
     *
     * @return
     */
    @GetMapping("/logs")
    public ResponseEntity<StreamingResponseBody> logs() {
        StreamingResponseBody body = new StreamingResponseBody() {
            @Override
            public void writeTo(OutputStream outputStream) throws IOException {
                log.info("outputStream={}", outputStream);
                try {
                    for (int i = 0; i < 100; i++) {
                        Thread.sleep(100);

                        String message = "logs " + i + "     \n";
                        outputStream.write(message.getBytes(StandardCharsets.UTF_8));
                        outputStream.flush();
                        log.info("output to client: {}", message);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    outputStream.write("unexpected exception".getBytes(StandardCharsets.UTF_8));
                    outputStream.flush();
                } finally {
                    outputStream.write("finished\n".getBytes(StandardCharsets.UTF_8));
                    outputStream.flush();
                }
            }
        };

        log.info("http end");
        return ResponseEntity.status(HttpStatus.OK)
                .contentType(MediaType.parseMediaType("text/plain; charset=UTF-8"))
                .body(body);
    }
}
